package sample;

import javafx.application.Application;
import javafx.embed.swing.SwingFXUtils;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.*;
import javafx.scene.paint.Paint;
import javafx.scene.text.Font;
import javafx.stage.FileChooser;
import javafx.stage.Stage;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;


public class Main extends Application {
    public static void main(String[] args)
    {
        launch(args);
    }

    private Button b1;
    private Button b2;
    private Button b3;
    private Label label;

    private Image image;
    private ImageView imageView;

    @Override
    public void start(Stage primaryStage) throws Exception
    {
        primaryStage.setHeight(650);
        primaryStage.setWidth(803);
        primaryStage.setTitle("图像处理基础Demo");
        primaryStage.getIcons().add(new Image("/icon/mingre.jpg"));

        b1 = new Button("Open");
        b2 = new Button("Run");
        b3 = new Button("Save");
        label = new Label("Time:");

        //
        // openBtn
        //
//        b1.setLayoutX(12);
//        b1.setLayoutY(12);
        //b1.setMinWidth(80);
        b1.setPrefWidth(80);
        b1.setPrefHeight(40);

        Font font = Font.font("Consolas", 16);
        BackgroundFill bgf = new BackgroundFill(Paint.valueOf("8FBC8F"), new CornerRadii(20), new Insets(5));
        Background bg = new Background(bgf);
        BorderStroke stroke = new BorderStroke(Paint.valueOf("#8A2BE2"), BorderStrokeStyle.SOLID, new CornerRadii(20), new BorderWidths(5));
        Border border = new Border(stroke);

        //b1.setFont(font);
        //b1.setBackground(bg);
        //b1.setBorder(border);
        String buttonStyle = "-fx-background-color: #8FBC8F; -fx-stroke:#8A2BE2; -fx-background-radius: 20px; -fx-font-size: 14px; -fx-font-family: Consolas";
        b1.setStyle(buttonStyle);
        b1.setOnAction(loadEventListener);

        //
        // algBtn
        //
//        b2.setLayoutX(12);
//        b2.setLayoutY(68);
        //b2.setMinWidth(80);
        b2.setPrefWidth(80);
        b2.setPrefHeight(40);
        b2.setStyle(buttonStyle);
        b2.setOnAction(algEventListener);

        //
        // saveBtn
        //
//        b3.setLayoutX(12);
//        b3.setLayoutY(122);
        //b3.setMinWidth(80);
        b3.setPrefWidth(80);
        b3.setPrefHeight(40);
        b3.setStyle(buttonStyle);
        b3.setOnAction(saveEventListener);

        //
        // time cost label
        //
//        label.setLayoutX(12);
//        label.setLayoutY(167);
        label.setPrefHeight(100);
        label.setPrefWidth(40);
        label.setStyle("-fx-font-size: 14px; -fx-font-family: Consolas");

        //
        // imageview
        //
        imageView = new ImageView();
        imageView.setPreserveRatio(true);


        //
        // == anchor pane layout
        //
        AnchorPane ap = new AnchorPane();
        ap.setStyle("-fx-background-color: #F5FFFA");

        ap.setLeftAnchor(b1, 12.0);
        ap.setTopAnchor(b1, 12.0);


        ap.setLeftAnchor(b2, 12.0);
        ap.setTopAnchor(b2, 68.0);

        ap.setLeftAnchor(b3, 12.0);
        ap.setTopAnchor(b3, 122.0);

        ap.setLeftAnchor(label, 12.0);
        ap.setTopAnchor(label, 167.0);

        AnchorPane ap2 = new AnchorPane();
        ap2.setStyle("-fx-background-color: #FFFFCC");
        ap2.getChildren().add(imageView);

        // Bind the imageView width property to gridPane width property
        // So, if width of gridPane change, the width of imageView automatically will be change
        imageView.fitWidthProperty().bind(ap2.widthProperty());
        imageView.fitHeightProperty().bind(ap2.heightProperty());

        ap.setLeftAnchor(ap2, 120.0);
        ap.setRightAnchor(ap2, 10.0);
        ap.setTopAnchor(ap2, 10.0);
        ap.setBottomAnchor(ap2, 10.0);

        ap.setPadding(new Insets(10)); //内边距
        ap.getChildren().addAll(b1, b2, b3, label, ap2);


        //group.setOpacity(0.5);
        //System.out.println(group.contains(12, 12)); //只检查组件左上角顶点。
//        Object[] qq = group.getChildren().toArray();
//        System.out.println(qq.length);

        Scene scene = new Scene(ap);
        primaryStage.setScene(scene);

        primaryStage.show();
    }




    EventHandler<ActionEvent> loadEventListener = t -> {
        FileChooser fileChooser = new FileChooser();

        FileChooser.ExtensionFilter extFilterJPG = new FileChooser.ExtensionFilter("JPG files (*.jpg)", "*.JPG");
        FileChooser.ExtensionFilter extFilterPNG = new FileChooser.ExtensionFilter("PNG files (*.png)", "*.PNG");

        fileChooser.getExtensionFilters().addAll(extFilterJPG, extFilterPNG);

        //Show open file dialog
        File file = fileChooser.showOpenDialog(null);

        if (file != null) {
            image = new Image(file.toURI().toString());
            imageView.setImage(image);
        }
    };

    //https://www.genuinecoder.com/save-files-javafx-filechooser/
    EventHandler<ActionEvent> saveEventListener = t -> {
        FileChooser fileChooser = new FileChooser();
        FileChooser.ExtensionFilter extFilterJPG = new FileChooser.ExtensionFilter("JPG files (*.jpg)", "*.jpg");
        FileChooser.ExtensionFilter extFilterPNG = new FileChooser.ExtensionFilter("PNG files (*.png)", "*.png");

        fileChooser.getExtensionFilters().addAll(extFilterJPG, extFilterPNG);

        File file = fileChooser.showSaveDialog(null);
        if(file!=null) {
            BufferedImage bImage = SwingFXUtils.fromFXImage(image, null);
            try {
                ImageIO.write(bImage, "png", file);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    };

    //https://www.geeksforgeeks.org/image-processing-java-set-4-colored-image-negative-image-conversion/?ref=rp
    //SwingFXUtils.fromFXImage
    //SwingFXUtils.toFXImage
    EventHandler<ActionEvent> algEventListener = t -> {
        long procStartTime=System.currentTimeMillis();   //获取开始时间

        int width = (int)(image.getWidth());
        int height = (int)(image.getHeight());
        BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        SwingFXUtils.fromFXImage(image, bufferedImage);

        long algStartTime=System.currentTimeMillis();   //获取开始时间
        // Convert to negative
        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < width; x++)
            {
                int p = bufferedImage.getRGB(x,y);
                int a = (p>>24)&0xff;
                int r = (p>>16)&0xff;
                int g = (p>>8)&0xff;
                int b = p&0xff;

                //subtract RGB from 255
                r = 255 - r;
                g = 255 - g;
                b = 255 - b;

                //set new RGB value
                p = (a<<24) | (r<<16) | (g<<8) | b;
                bufferedImage.setRGB(x, y, p);
            }
        }
        long algEndTime = System.currentTimeMillis();

        image = SwingFXUtils.toFXImage(bufferedImage, null);
        imageView.setImage(image);

        long procEndTime=System.currentTimeMillis(); //获取结束时间
        long algCost = algEndTime - algStartTime;
        long procCost = procEndTime - procStartTime;
        //label.setText("Time:\n" + algCost + "/" + procCost + "ms");
        label.setText("Time:\n" + algCost + "ms");
    };

}
